<#include "/templates/taglibs.ftl" />
<#include "/templates/function.ftl" />
<!DOCTYPE html>
<html lang="zh-cn">
    <head>
        <meta charset="utf-8">
        <link rel="stylesheet" href="${contextPath}/assets/plugins/layui/css/layui.css" media="all" />
        <style>
            p {
                margin-bottom: 10px;
                font-size: 15px;
                color: #393D49;
                font-weight: 400;
                line-height: 1.8;
            }
            .site-content {
                background-color: #fff;
                padding: 20px 0 10px 20px;
            }
            .site-h1 {
                margin-bottom: 20px;
                line-height: 60px;
                padding-bottom: 10px;
                color: #393D49;
                border-bottom: 1px solid #eee;
                font-size: 28px;
                font-weight: 400;
            }
        </style>
    </head>
    <body>
        <div class="layui-fluid layui-container">
            <div class="layui-row site-content">
                <div class="layui-col-md12">
                    <h1 class="site-h1">OAuth2实现单点登录</h1>
                    <p>OAuth 2.0 是目前最流行的授权机制，用来授权第三方应用，获取用户数据。</p>
                    <p>简单说，OAuth 就是一种授权机制。数据的所有者告诉系统，同意授权第三方应用进入系统，获取这些数据。系统从而产生一个短期的进入令牌（token），用来代替密码，供第三方应用使用。</p>
                    <p>令牌（token）与密码（password）的作用是一样的，都可以进入系统，但是有三点差异。</p>
                    <p>-令牌是短期的，到期会自动失效，用户自己无法修改。密码一般长期有效，用户不修改，就不会发生变化。</p>
                    <p>-令牌可以被数据所有者撤销，会立即失效。</p>
                    <p>-令牌有权限范围.</p>
                    <br/>
                    <p>OAuth 2.0 对于如何颁发令牌的细节，规定得非常详细。具体来说，一共分成四种授权类型（authorization grant），即四种颁发令牌的方式，适用于不同的互联网场景</p>
                    <p>-授权码（authorization-code）</p>
                    <p>-隐藏式（implicit）</p>
                    <p>-密码式（password）</p>
                    <p>-客户端凭证（client credentials）</p>
                    <p><b>不管以上哪一种授权方式，第三方应用申请令牌之前，都必须先到系统备案，说明自己的身份，然后会拿到两个身份识别码：客户端 ID（client ID）和客户端密钥（client secret）。这是为了防止令牌被滥用，没有备案过的第三方应用，是不会拿到令牌的。</b></p>
                    </br>
                     <fieldset class="layui-elem-field layui-field-title site-title">
                        <legend><a name="get">授权码（authorization code）</a></legend> 
                    </fieldset>
                    <p>系统中提供了授权码（authorization-code）方式供三方应用使用，下面主要介绍授权码模式的使用</p>
                    <p>授权码（authorization code）方式，指的是第三方应用先申请一个授权码，然后再用该码获取令牌。</p>
                    <p>这种方式是最常用的流程，安全性也最高，它适用于那些有后端的 Web 应用。授权码通过前端传送，令牌则是储存在后端，而且所有与资源服务器的通信都在后端完成。这样的前后端分离，可以避免令牌泄漏。</p>
                    <p>第一步，客户端A网站提供一个链接，用户点击后就会跳转到服务端B网站，授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接。</p>
                    <pre class="layui-code" lay-skin="notepad">
https://b.com/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read
                    </pre>
                    <p>上面 URL 中，response_type参数表示要求返回授权码（code），client_id参数让 B 知道是谁在请求，redirect_uri参数是 B 接受或拒绝请求后的跳转网址，scope参数表示要求的授权范围</p>
                    <p>第二步，用户跳转后，B 网站会要求用户登录，然后询问是否同意给予 A 网站授权。用户表示同意，这时 B 网站就会跳回redirect_uri参数指定的网址。跳转时，会传回一个授权码，就像下面这样。</p>
                    <pre class="layui-code" lay-skin="notepad">
https://a.com/callback?code=AUTHORIZATION_CODE
                    </pre>
                    <p>上面 URL 中，code参数就是授权码</p>
                    <p>第三步，A 网站拿到授权码以后，就可以在后端，向 B 网站请求令牌。</p>
                    <pre class="layui-code" lay-skin="notepad">
https://b.com/oauth/token?client_id=CLIENT_ID&client_secret=CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL
                    </pre>
                    <p>上面 URL 中，client_id参数和client_secret参数用来让 B 确认 A 的身份（client_secret参数是保密的，因此只能在后端发请求），grant_type参数的值是AUTHORIZATION_CODE，表示采用的授权方式是授权码，code参数是上一步拿到的授权码，redirect_uri参数是令牌颁发后的回调网址。</p>
                    <p>第四步，B 网站收到请求以后，就会颁发令牌。具体做法是向redirect_uri指定的网址，发送一段 JSON 数据。</p>
                     <pre class="layui-code" lay-skin="notepad">
{    
  "access_token":"ACCESS_TOKEN",
  "token_type":"bearer",
  "expires_in":86400,
  "refresh_token":"REFRESH_TOKEN",
  "scope":"read"
}
                    </pre>
                    <p>上面 JSON 数据中，access_token字段就是令牌，A 网站在后端拿到了。</p>
                    <p>第五步，A网站根据获取的access_token调用相关用户服务接口，即可获取到用户数据</p>
            </div>
        </div>
    </body>
    <script type="text/javascript" src="${contextPath}/assets/plugins/layui/layui.js"></script>
    <script>
        layui.use('code', function(){ 
            layui.code({
                encode: true
            }); 
          });
    </script>
</html>